fix(federation): remove plaintext auth token from error log in getSharedSecret#41578
fix(federation): remove plaintext auth token from error log in getSharedSecret#41578DeepDiver1975 wants to merge 2 commits into
Conversation
…redSecret When getSharedSecret received an invalid token it logged both the attacker-supplied token and the expected valid token in plaintext: 'got "X" but expected "Y"'. Since the endpoint is @publicpage, any unauthenticated caller could trigger this log entry at will for any trusted server URL, potentially exposing the valid federation token to anyone with log-read access. Remove the dbHandler->getToken() call that existed solely to populate the log message, and replace the message with a non-disclosing string. Signed-off-by: Thomas Müller <thomas.mueller@owncloud.com> Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
|
Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a changelog item based on your changes. |
Signed-off-by: Thomas Müller <1005065+DeepDiver1975@users.noreply.github.com>
DeepDiver1975
left a comment
There was a problem hiding this comment.
Code Review — fix(federation): remove plaintext auth token from error log in getSharedSecret
Overview: getSharedSecret (@PublicPage) logged the valid stored token in plaintext on authentication failure: got "X" but expected "Y". Since any unauthenticated caller can trigger this log entry for any trusted server URL, anyone with log-read access could harvest the valid federation token and replay it. The fix removes the getToken() call and replaces the log message with a non-disclosing string.
Correctness
The change is minimal: one line removed (the $expectedToken DB fetch), one string literal updated. The isValidToken() check and the 403 response path are unchanged. ✅
Does dbHandler->getToken() get called twice now? No — isValidToken() internally calls getToken() and does the comparison itself. The additional getToken() call that was removed existed solely to populate the log message. Removing it is correct. ✅
Test
testGetSharedSecretDoesNotLogTokenValues asserts that the logger->error message contains neither the attacker-supplied token nor the stored token:
$this->logicalAnd(
$this->logicalNot($this->stringContains($attackerToken)),
$this->logicalNot($this->stringContains($storedToken))
)This directly tests the security property, not just that a log call happened. The test would fail against the old code (which embeds both values) and pass against the new code. ✅
Note in PR body: "merge that one first to avoid conflicts" (referring to #41579). Both PRs touch OCSAuthAPIController.php but at different line ranges, so a clean merge order matters. Review team should coordinate.
Summary
| Aspect | Assessment |
|---|---|
| Token removed from log | ✅ Both attacker-supplied and stored token scrubbed |
| Extra DB call removed | ✅ No longer calls getToken() redundantly |
| Test | ✅ Directly asserts neither value appears in log message |
| Merge dependency |
Verdict: Ready to merge (after #41579).
dj4oC
left a comment
There was a problem hiding this comment.
Removes the submitted/expected federation shared-secret token values from the error log message in OCSAuthAPIController::getSharedSecret().
Findings
- Security — CWE-532 (Insertion of Sensitive Information into Log File), OWASP A09:2021: the fix for the stated call site is correct and well-tested (new test asserts neither token value appears in the logged message). However, the changelog's claim that "token values have been removed from the log message" is incomplete —
apps/federation/lib/BackgroundJob/GetSharedSecret.phpsends the same token as a GET query parameter, and on any non-403 HTTP failure calls$this->logger->logException($e, ...). Guzzle exception messages conventionally embed the full request URI including the query string, so the plaintext token can still leak into logs via this different, untouched code path.RequestSharedSecret.phpalready sends its token via POST body — the same pattern should be applied here, or the query string should be scrubbed before exception logging. - Stability: no findings —
isValidToken()'s actual auth decision is untouched, only the log line changed. - Performance: net positive — removes a redundant DB lookup (
getToken($url)) that existed only to populate the log string. - Test coverage: good for the fixed call site; no coverage exists (or is feasible without deeper refactor) for the
GetSharedSecret.phpleak path noted above.
Verdict
Changes requested — the fix is correct as far as it goes, but ships an incomplete claim ("token removed from log") while a second, real leak path remains open in the same feature area. Recommend fixing GetSharedSecret.php in the same PR (or immediately after) rather than merging with the overclaim uncorrected.
🤖 Automated review by Claude Code (security · stability · performance · coverage)
Generated by Claude Code
Summary
getSharedSecret(@publicpage) logged both the submitted and expected tokens in plaintext on failure:got "X" but expected "Y"getToken()DB call that existed only to populate the log, replacing the message with a generic non-disclosing stringSecurity Impact
Medium — requires secondary log-read access to exploit; unauthenticated trigger
Note
This PR touches the same file as
security/fix-federation-token-oracle— merge that one first to avoid conflicts.Test plan
testGetSharedSecretDoesNotLogTokenValuesasserts neither attacker nor stored token appears in the logged string; fails without fixmake test TEST_PHP_SUITE=apps/federation🤖 Generated with Claude Code